package timing.ukulele.third.msgChannel.handle.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxCpErrorMsgEnum;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpMessageServiceImpl;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.article.MpnewsArticle;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import me.chanjar.weixin.cp.bean.message.WxCpMessage;
import me.chanjar.weixin.cp.bean.message.WxCpMessageSendResult;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import timing.ukulele.third.constant.MessageConstant;
import timing.ukulele.third.constant.CommonConstant;
import timing.ukulele.third.dictionary.msg.MsgChannelType;
import timing.ukulele.third.dictionary.msg.SendMessageType;
import timing.ukulele.third.msgChannel.handle.BaseHandler;
import timing.ukulele.third.msgChannel.model.RecallTaskInfo;
import timing.ukulele.third.msgChannel.model.SendTaskInfo;
import timing.ukulele.third.msgChannel.model.content.EnterpriseWeChatContentModel;
import timing.ukulele.third.msgChannel.param.HandleMessageBaseResponse;
import timing.ukulele.third.msgChannel.utils.AccountUtils;
import java.util.List;
import java.util.Map;

/**
 * 企业微信推送处理
 * https://developer.work.weixin.qq.com/document/path/90235
 * @author zh
 */
@Component
@Slf4j
public class EnterpriseWeChatHandler extends BaseHandler {

    private static final String WE_CHAT_RECALL_KEY_PREFIX = "WECHAT_RECALL_";
    private static final String WE_CHAT_RECALL_BIZ_TYPE = "EnterpriseWeChatHandler#recall";
    @Autowired
    private AccountUtils accountUtils;
    @Autowired
    private StringRedisTemplate redisTemplate;

    public EnterpriseWeChatHandler() {
        channelCode = MsgChannelType.ENTERPRISE_WE_CHAT.getCode();
    }

    @Override
    public HandleMessageBaseResponse send(SendTaskInfo taskInfo) {
        // 构造返回值
        HandleMessageBaseResponse result = new HandleMessageBaseResponse();
        try {
            // 获取微信账号信息
            WxCpDefaultConfigImpl accountConfig = accountUtils.getAccountById(
                    taskInfo.getSendAccountId(), WxCpDefaultConfigImpl.class);
            WxCpMessageServiceImpl messageService = new WxCpMessageServiceImpl(initService(accountConfig));
            WxCpMessageSendResult wxCpMessageSendResult = messageService.send(buildWxCpMessage(taskInfo, accountConfig.getAgentId()));
            log.info("EnterpriseWeChatHandler#send response:{},params:{}", JSON.toJSONString(wxCpMessageSendResult), JSON.toJSONString(taskInfo));
            // 发送成功后记录TaskId，用于消息撤回(支持24小时之内)
            if (Integer.valueOf(WxCpErrorMsgEnum.CODE_0.getCode()).equals(wxCpMessageSendResult.getErrCode())) {
                result.setHandleFlag(true);
            }else{
                result.setHandleFlag(false);
            }
            result.setHandleMessage(wxCpMessageSendResult.getErrMsg());
       } catch (Exception e) {
            log.error("EnterpriseWeChatHandler#send fail:{},params:{}",
                    Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo));
            result.setHandleFlag(false);
            result.setHandleMessage(Throwables.getStackTraceAsString(e));
        }
        return result;
    }

    /**
     * 初始化 WxCpServiceImpl 服务接口
     *
     * @param config
     * @return
     */
    private WxCpService initService(WxCpDefaultConfigImpl config) {
        WxCpServiceImpl wxCpService = new WxCpServiceImpl();
        wxCpService.setWxCpConfigStorage(config);
        return wxCpService;
    }

    /**
     * 构建企业微信下发消息的对象
     *
     * @param taskInfo
     * @param agentId  应用ID
     * @return
     */
    private WxCpMessage buildWxCpMessage(SendTaskInfo taskInfo, Integer agentId) {
        String userId;
        if (MessageConstant.SEND_ALL.equals(CollUtil.getFirst(taskInfo.getReceiver()))) {
            userId = CollUtil.getFirst(taskInfo.getReceiver());
        } else {
            userId = StringUtils.join(taskInfo.getReceiver(), CommonConstant.RADICAL);
        }
        EnterpriseWeChatContentModel contentModel = (EnterpriseWeChatContentModel) taskInfo.getContentModel();

        // 通用配置
        WxCpMessage wxCpMessage = new WxCpMessage();
        if (SendMessageType.TEXT.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.TEXT().content(contentModel.getContent()).build();
        } else if (SendMessageType.IMAGE.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.IMAGE().mediaId(contentModel.getMediaId()).build();
        } else if (SendMessageType.VOICE.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.VOICE().mediaId(contentModel.getMediaId()).build();
        } else if (SendMessageType.VIDEO.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.VIDEO().mediaId(contentModel.getMediaId()).description(contentModel.getDescription()).title(contentModel.getTitle()).build();
        } else if (SendMessageType.FILE.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.FILE().mediaId(contentModel.getMediaId()).build();
        } else if (SendMessageType.TEXT_CARD.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.TEXTCARD().url(contentModel.getUrl()).title(contentModel.getTitle()).description(contentModel.getDescription()).btnTxt(contentModel.getBtnTxt()).build();
        } else if (SendMessageType.NEWS.getCode().equals(contentModel.getSendType())) {
            List<NewArticle> newArticles = JSON.parseArray(contentModel.getArticles(), NewArticle.class);
            wxCpMessage = WxCpMessage.NEWS().articles(newArticles).build();
        } else if (SendMessageType.MP_NEWS.getCode().equals(contentModel.getSendType())) {
            List<MpnewsArticle> mpNewsArticles = JSON.parseArray(contentModel.getMpNewsArticle(), MpnewsArticle.class);
            wxCpMessage = WxCpMessage.MPNEWS().articles(mpNewsArticles).build();
        } else if (SendMessageType.MARKDOWN.getCode().equals(contentModel.getSendType())) {
            wxCpMessage = WxCpMessage.MARKDOWN().content(contentModel.getContent()).build();
        } else if (SendMessageType.MINI_PROGRAM_NOTICE.getCode().equals(contentModel.getSendType())) {
            Map contentItems = JSON.parseObject(contentModel.getContentItems(), Map.class);
            wxCpMessage = WxCpMessage.newMiniProgramNoticeBuilder().appId(contentModel.getAppId()).page(contentModel.getPage()).emphasisFirstItem(contentModel.getEmphasisFirstItem()).contentItems(contentItems).title(contentModel.getTitle()).description(contentModel.getDescription()).build();
        } else if (SendMessageType.TEMPLATE_CARD.getCode().equals(contentModel.getSendType())) {

        }

        wxCpMessage.setAgentId(agentId);
        wxCpMessage.setToUser(userId);
        return wxCpMessage;
    }

    /**
     * 撤回企业微信应用消息；
     * https://developer.work.weixin.qq.com/document/path/94867
     *
     * @param recallTaskInfo
     */
    @Override
    public HandleMessageBaseResponse recall(RecallTaskInfo recallTaskInfo) {
        try {
            WxCpDefaultConfigImpl accountConfig = accountUtils.getAccountById(recallTaskInfo.getSendAccountId(), WxCpDefaultConfigImpl.class);
            WxCpMessageServiceImpl messageService = new WxCpMessageServiceImpl(initService(accountConfig));

            // todo 执行撤回消息逻辑

        } catch (Exception e) {
            log.error("EnterpriseWeChatHandler#recall fail:{}", Throwables.getStackTraceAsString(e));
        }
        return HandleMessageBaseResponse.builder().handleFlag(true).build();
    }

}

